package org.snail.excel.annotation;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.snail.excel.common.ExcelDataFormatter;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by WJ on 2017/12/6.
 */
public class ExcelSheetReaderProcessor {

    private static Logger LOGGER = Logger.getLogger(ExcelSheetReaderProcessor.class);

    //内存中的缓存记录数
    private static int intRowAccess = 100;

    /**
     * 读取sheet数据到List中
     * @param sheet
     * @param startRow
     * @param t
     * @param <T>
     * @return
     */

    public <T> List<T> readFromExcelSheet(Sheet sheet,int startRow, Class<T> t) {
        List<T> resultList = new ArrayList<T>();
        try {
            for (Row row : sheet) {
                System.out.println("开始遍历第" + row.getRowNum() + "行数据：");   //遍历excel的行数
                if (row.getRowNum() < startRow){
                    continue;
                }
                //遍历所有的列，并且赋值
                T oneExcelObj = matchRow2Bean(row, t);
                if (null == oneExcelObj) {
                    LOGGER.error("excel读取数据，有一行为空！Excel中的行数：" + row.getRowNum() + startRow);
                }else {
                    resultList.add(oneExcelObj);
                }
            }




//=============================================老版本excel解析=============================================
//            //从指定行开始读取
//            for (int i=startRow; i<=sheet.getLastRowNum(); i++) {
//                Row row = sheet.getRow(i);
//                T matchT =  matchRow2Bean(row, t);
//                if(null!=matchT) {
//                    resultList.add(matchT);
//                }
//
//                if(i%intRowAccess==0) {
//                    if(sheet instanceof SXSSFSheet)
//                        ((SXSSFSheet)sheet).flushRows();
//                }
//
//            }
//            ========================================老版本excel解析 结束========================================================
        } catch (Exception e) {
            LOGGER.error(e.getStackTrace(),e);
        }
        return resultList;
    }

    /**
     * 把一行数据转换为JAVA Bean 对象
     * @param row
     * @param t
     * @param <T>
     * @return
     */

    public <T> T matchRow2Bean(Row row, Class<T> t) {
        T newInstance = null;
        try {
            if(t != null) {
                //判断此类为Excel Bean 对象
                newInstance =  t.newInstance();
                ExcelBean excelBean = newInstance.getClass().getAnnotation(ExcelBean.class);
                if(excelBean!=null && excelBean.isExcelBean()) {
                    Field[] fields = newInstance.getClass().getDeclaredFields();

                    //遍历字段，转换为Bean对象XSSFWorkbook
                    for (Field field:fields) {
                        field.setAccessible(true);
                        ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);
                        if(excelColumn!=null && excelColumn.skip()!=true) {
                            //1、获取单元格的值
                            if(excelColumn.position()>=0 ) {
                                int ca = excelColumn.position();
//                                String province = row.getCell(4).getStringCellValue();
                                Cell cell = row.getCell(ca);
                                if(cell!=null) {
                                    Object obj = getCellValue(cell);
//                                    Object obj = cell.toString();
                                    //2、获取单元格的转换器

                                    if(null!=obj) {
                                        Class edfCls = excelColumn.dataFormatter();
                                        ExcelDataFormatter excelDataFormatter = null;
                                        if (null != edfCls && !(edfCls instanceof Object)) {
                                            excelDataFormatter = (ExcelDataFormatter) edfCls.newInstance();
                                        }

                                        //有值时，进行转换，给Bean对象设置值
                                        translateCell2Field(newInstance, obj, field, excelDataFormatter, cell);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    newInstance = null;
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getStackTrace(),e);
        }
        return newInstance;
    }

    /**
     * 给对象各个属性设置值
     * @param t
     * @param value
     * @param field
     * @param edf
     * @param <T>
     * @return
     */
    private <T> T translateCell2Field(T t, Object value,Field field, ExcelDataFormatter edf, Cell cell) {
        //1、转换器不为空时，进行数据转换
        if(null != edf) {
            value = edf.translate(cell, value);
        }
        try {
            if(field.getType().equals(Date.class)) {
               Date DateValue = parseDate((String)value,"yyyy/MM/dd");
//                if(value.getClass().equals(Date.class)) {
                    field.set(t, DateValue);
//                }
            } else if(field.getType().equals(String.class)) {
                if(value.getClass().equals(String.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, value.toString());
                }
            } else if(field.getType().equals(Long.class)) {
                if(value.getClass().equals(Long.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, Long.parseLong(value.toString()));
                }
            } else if(field.getType().equals(Integer.class)) {
                if(value.getClass().equals(Integer.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, Integer.parseInt(value.toString()));
                }
            } else if(field.getType().equals(BigDecimal.class)) {
                if(value.getClass().equals(BigDecimal.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, BigDecimal.valueOf(Double.parseDouble(value.toString())));
                }
            } else if(field.getType().equals(Boolean.class)) {
                if(value.getClass().equals(Boolean.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, Boolean.parseBoolean(value.toString()));
                }
            } else if(field.getType().equals(Float.class)) {
                if(value.getClass().equals(Float.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, Float.parseFloat(value.toString()));
                }
            } else if(field.getType().equals(Double.class)) {
                if(value.getClass().equals(Double.class)) {
                    field.set(t, value);
                } else {
                    field.set(t, Double.parseDouble(value.toString()));
                }
            }
        } catch (Exception e) {
            LOGGER.error(e.getStackTrace(),e);
        }

        return t;
    }

    /**
     * 获取单元格的值
     * @param cell
     * @return
     */
    private Object getCellValue(Cell cell){
        Object o = null;
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_BOOLEAN:
                o = cell.getBooleanCellValue();
                break;
            case Cell.CELL_TYPE_NUMERIC:
//                o = cell.getNumericCellValue();
                DataFormatter dataFormatter = new DataFormatter();
                o = dataFormatter.formatCellValue(cell);
                break;
            case Cell.CELL_TYPE_STRING:
                o = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_BLANK:
                o = null;
                break;
            case Cell.CELL_TYPE_FORMULA:
                o = cell.getCellFormula();
                break;
            default:
                o = null;
                break;
        }
        return o;
    }

    private Date parseDate(String str, String parsePattern) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(parsePattern);
        return simpleDateFormat.parse(str);
    }


}
